package com.vip.fdfs.controller;

import com.vip.common.constant.SysConsts;
import com.vip.common.constant.UrlConsts;
import com.vip.common.exception.BusinessException;
import com.vip.common.response.ErrorCode;
import com.vip.common.response.RestResponse;
import com.vip.common.response.RestResponses;
import com.vip.common.response.Result;
import com.vip.common.util.EmptyUtils;
import com.vip.fdfs.dto.AddFileDTO;
import com.vip.fdfs.dto.GetFileDTO;
import com.vip.fdfs.dto.ImageReturnDTO;
import com.vip.fdfs.entity.SysFastdfsFile;
import com.vip.fdfs.service.IFastdfsFileService;
import com.vip.fdfs.service.IFileBaseInfoService;
import com.vip.fdfs.util.EncodingUtils;
import com.vip.fdfs.util.FileDFSUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * 文件传输控制器
 *
 * @author wgb
 * @date 2019/12/22 17:34
 */
@Slf4j
@RestController
@RequestMapping(value = UrlConsts.API + "/file")
public class FileTransferController {
    @Autowired
    private FileDFSUtils fileDFSUtils;
    @Autowired
    private IFastdfsFileService fastdfsFileService;
    @Autowired
    private IFileBaseInfoService fileBaseInfoService;

    /**
     * 文件删除
     *
     * @param fileId 文件ID
     * @return
     */
    @DeleteMapping(value = "/delete/{fileId}")
    public RestResponse<String> deleteByPath(@PathVariable("fileId") String fileId) {
        return RestResponses.newResponseFromResult(fastdfsFileService.deleteFileById(fileId));
    }

    /**
     * 图片文件上传
     *
     * @param file        文件
     * @param bindingId   绑定对象Id
     * @param description 描述
     * @param fileType    文件类型
     * @return
     */
    @ApiOperation(value = "上传图片")
    @PostMapping(value = "/uploadImage")
    public RestResponse<ImageReturnDTO> uploadImage(@RequestParam(required = false) String bindingId, @RequestParam(required = false) String description, @RequestParam(required = false) String fileType, @RequestParam("file") MultipartFile file) {
        return RestResponses.newResponseFromResult(fastdfsFileService.uploadImage(bindingId, description, fileType, file));
    }

    /**
     * 非图片文件上传
     *
     * @param file 文件
     * @return
     */
    @ApiOperation(value = "上传文件")
    @PostMapping(value = "/uploadFile", headers = "content-type=multipart/form-data")
    public RestResponse<String> uploadFile(@RequestParam(required = false) String bindingId, @RequestParam(required = false) String description, @RequestParam(required = false) String fileType, @RequestParam("file") MultipartFile file) {
        Result<String> uploadResult = fileDFSUtils.uploadFile(file);
        if (uploadResult.isSuccess()) {
            // 如果是视频文件则截取视频截图，返回截图存储路径
            String videoScreenshot = fastdfsFileService.uploadFetchFrame(file);
            AddFileDTO dto = new AddFileDTO().setThumbImagePath(videoScreenshot);
            dto.setFileName(file.getOriginalFilename()).setPath(uploadResult.getData()).setBindingId(bindingId).setDescription(description).setFileType(fileType);
            return RestResponses.newResponseFromResult(fastdfsFileService.uploadFile(dto));
        } else {
            return RestResponses.newFailResponse(uploadResult.getErrorCode(), uploadResult.getDescription());
        }
    }

    /**
     * 文件下载
     *
     * @param fileId   文件路径
     * @param isSource 是否使用源文件名，否：系统重新命名
     */
    @ApiOperation(value = "文件下载")
    @GetMapping("/download/{fileId}")
    public void downloadByPath(@PathVariable("fileId") String fileId, @RequestParam(required = false) Boolean isSource, HttpServletRequest request, HttpServletResponse response) {
        OutputStream outputStream = null;
        InputStream inputStream = null;
        try {
            String fileUrl;
            Result<GetFileDTO> fastdfsFile = fileBaseInfoService.getFileDetails(fileId);
            if (fastdfsFile.isSuccess()) {
                fileUrl = fastdfsFile.getData().getPath();
            } else {
                throw new BusinessException(fastdfsFile.getErrorCode(), fastdfsFile.getDescription());
            }
            String filename;
            if (!EmptyUtils.basicIsEmpty(isSource) && isSource) {
                filename = fastdfsFile.getData().getFileName();
                String suffix = fastdfsFile.getData().getSuffix();
                if (!EmptyUtils.basicIsEmpty(suffix)) {
                    filename = filename + "." + suffix;
                }
            } else {
                filename = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
            }
            inputStream = fileDFSUtils.downloadFile(fileUrl);
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + EncodingUtils.convertToFileName(request, filename));
            // 获取输出流
            outputStream = response.getOutputStream();
            IOUtils.copy(inputStream, outputStream);
        } catch (IOException e) {
            log.error("文件下载出错", e);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 文件查看，用于查看完整图片
     *
     * @param fileId 文件ID
     * @return
     */
    @GetMapping("/view/{fileId}")
    public ResponseEntity<byte[]> viewImage(@PathVariable String fileId) {
        String fileUrl;
        Result<SysFastdfsFile> getFileInfoResult = fastdfsFileService.getFileInfoById(fileId);
        SysFastdfsFile fileInfo = getFileInfoResult.getData();
        if (getFileInfoResult.isSuccess()) {
            if (SysConsts.IMAGE_TYPE.contains(fileInfo.getSuffix())) {
                fileUrl = fileInfo.getPath();
            } else {
                throw new BusinessException(ErrorCode.FILE_ERROR, "非图片/PDF类型请先下载");
            }
        } else {
            throw new BusinessException(getFileInfoResult.getErrorCode(), getFileInfoResult.getDescription());
        }
        byte[] bytes = fileDFSUtils.viewFile(fileUrl);
        HttpHeaders headers = new HttpHeaders();
        if ("pdf".equals(fileInfo.getSuffix().toLowerCase())) {
            headers.setContentType(MediaType.APPLICATION_PDF);
        } else {
            headers.setContentType(MediaType.IMAGE_JPEG);
        }
        HttpStatus statusCode = HttpStatus.OK;
        return new ResponseEntity<>(bytes, headers, statusCode);
    }

    /**
     * 查看图片缩略图
     *
     * @param fileId 图片文件ID
     * @return
     */
    @GetMapping("/viewthumb/{fileId}")
    public ResponseEntity<byte[]> viewImageThumb(@PathVariable String fileId) {
        String fileUrl;
        Result<String> getPathResult = fastdfsFileService.getImageThumbPath(fileId);
        if (getPathResult.isSuccess()) {
            fileUrl = getPathResult.getData();
        } else {
            throw new BusinessException(getPathResult.getErrorCode(), getPathResult.getDescription());
        }
        byte[] bytes = fileDFSUtils.viewFile(fileUrl);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG);
        HttpStatus statusCode = HttpStatus.OK;
        return new ResponseEntity<>(bytes, headers, statusCode);
    }

}
